package com.example.skillcinema.db.repositories

import android.media.Image
import com.bumptech.glide.load.ImageHeaderParser
import com.example.skillcinema.db.apis.RetrofitService
import com.example.skillcinema.db.displaymodels.FilmDisplayModel
import com.example.skillcinema.db.enums.FilmCollections
import com.example.skillcinema.db.enums.FilmOrderTypes
import com.example.skillcinema.db.enums.FilmTypes
import com.example.skillcinema.db.enums.GalleryImageTypes
import com.example.skillcinema.db.localdb.ApplicationDataBase
import com.example.skillcinema.db.models.Staff
import com.example.skillcinema.db.responses.FiltersResponse
import com.example.skillcinema.db.responses.ImageItemResponse
import com.example.skillcinema.db.responses.ImageResponse
import com.example.skillcinema.db.responses.PersonFilmResponse
import com.example.skillcinema.db.responses.PersonResponse
import com.example.skillcinema.extensions.sliceForPreview
import com.example.skillcinema.extensions.sliceToPages
import java.time.Month
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FilmRepository @Inject constructor(db: ApplicationDataBase) : BaseRepository(db) {

    private var cachedFilmographyFilms: Map<String, List<PersonFilmResponse>> = mapOf()

    suspend fun getPremiersFilms(
        year: Int,
        month: Month,
        page: Int,
    ): List<FilmDisplayModel> =
        RetrofitService.premierApi.getAll(year, month).items.sliceToPages(page).map {
            getFilmById(it.kinopoiskId)
        }

    suspend fun getTopFilms(
        type: FilmCollections = FilmCollections.TOP_POPULAR_ALL, page: Int
    ): List<FilmDisplayModel> =
        RetrofitService.filmsApi.getTopPopular(type, page).items.map { filmItem ->
            getFilmById(filmItem.kinopoiskId)
        }

    suspend fun getRandomFilteredFilms(
        country: Int, genre: Int, page: Int
    ): List<FilmDisplayModel> =
        RetrofitService.filmsApi.getAll(country, genre, page = page).items.map { filmItem ->
            getFilmById(filmItem.kinopoiskId)
        }

    suspend fun getFilters(): FiltersResponse = RetrofitService.filmsApi.getFilters()
    suspend fun searchFilm(
        countryId: Int?,
        genreId: Int?,
        orderType: FilmOrderTypes,
        filmType: FilmTypes,
        ratingFrom: Float?,
        ratingTo: Float?,
        yearFrom: Int?,
        yearTo: Int?,
        keyword: String?,
        page: Int
    ): List<FilmDisplayModel> = RetrofitService.filmsApi.getAll(
        countryId,
        genreId,
        orderType,
        filmType,
        ratingFrom,
        ratingTo,
        yearFrom,
        yearTo,
        keyword,
        page
    ).items.map { getFilmById(it.kinopoiskId) }

    suspend fun getSerials(page: Int): List<FilmDisplayModel> = RetrofitService.filmsApi.getSerials(
        FilmTypes.TV_SERIES, page
    ).items.map { serialItem ->
        getFilmById(serialItem.kinopoiskId)
    }

    suspend fun getSimilar(id: Int): List<FilmDisplayModel> =
        RetrofitService.filmsApi.getSimilar(id).items.map { related ->
            getFilmById(related.filmId)
        }

    suspend fun getStaffDetail(id: Int): PersonResponse =
        RetrofitService.filmsApi.getStaffDetail(id)

    suspend fun getStaffBestFilms(id: Int, page: Int): List<FilmDisplayModel> =
        getStaffDetail(id).films.sortedByDescending { it.filmId }.sliceToPages(page)
            .map { getFilmById(it.filmId) }

    suspend fun getStaffFilmographyKeys(id: Int): List<String> {
        val grouped = getStaffDetail(id).films.groupBy { it.professionKey ?: "UNKNOWN" }
        cachedFilmographyFilms = grouped
        return grouped.map { it.key.toString() }
    }

    suspend fun getStaffFilmography(
        id: Int, page: Int, key: String
    ): List<FilmDisplayModel> =
        cachedFilmographyFilms[key]?.sliceToPages(page)?.map { getFilmById(it.filmId) } ?: listOf()


    suspend fun getStaffFilmographyCount(id: Int): Int = getStaffDetail(id).films.count()

    suspend fun getNotEmptyGalleryTypes(id: Int): List<GalleryImageTypes> {
        val result: MutableList<GalleryImageTypes> = mutableListOf()
        GalleryImageTypes.entries.forEach {
            if (RetrofitService.filmsApi.getGallery(
                    id, page = FIRST_PAGE, it
                ).items.isNotEmpty()
            ) result.add(it)
        }
        return result
    }

    suspend fun getGalleryImageByType(
        id: Int, page: Int, type: GalleryImageTypes
    ): List<ImageItemResponse> = RetrofitService.filmsApi.getGallery(id, page, type).items
}